// 实现一
function deepClone(data) {
  const type = this.judgeType(data);
  let obj;

  if (type === "array") {
    obj = [];
  } else if (type === "object") {
    obj = {};
  } else {
    // 不再具有下一层次
    return data;
  }

  if (type === "array") {
    for (let i = 0, len = data.length; i < len; i++) {
      obj.push(deepClone(data[i]));
    }
  } else if (type === "object") {
    // 对原型上的方法也拷贝了....
    for (const key in data) {
      obj[key] = deepClone(data[key]);
    }
  }

  return obj;
}

function judgeType(obj) {
  // tostring会返回对应不同的标签的构造函数
  const toString = Object.prototype.toString;
  const map = {
    "[object Boolean]": "boolean",
    "[object Number]": "number",
    "[object String]": "string",
    "[object Function]": "function",
    "[object Array]": "array",
    "[object Date]": "date",
    "[object RegExp]": "regExp",
    "[object BigInt]": "bigint",
    "[object Symbol]": "symbol",
    "[object Undefined]": "undefined",
    "[object Null]": "null",
    "[object Object]": "object",
  };

  if (obj instanceof Element) {
    return "element";
  }

  return map[toString.call(obj)];
}

// // 实现二
// // 利用 WeakMap 解决循环引用
// const map = new WeakMap();
// function deepClone(obj) {
//   if (obj instanceof Object) {
//     if (map.has(obj)) {
//       return map.get(obj);
//     }
//     let newObj;
//     if (obj instanceof Array) {
//       newObj = [];
//     } else if (obj instanceof Function) {
//       newObj = function () {
//         return obj.apply(this, arguments);
//       };
//     } else if (obj instanceof RegExp) {
//       // 拼接正则
//       newObj = new RegExp(obj.source, obj.flags);
//     } else if (obj instanceof Date) {
//       newObj = new Date(obj);
//     } else {
//       newObj = {};
//     }

//     // 克隆一份对象出来
//     const desc = Object.getOwnPropertyDescriptors(obj);
//     const clone = Object.create(Object.getPrototypeOf(obj), desc);
//     map.set(obj, clone);

//     for (const key in obj) {
//       if (obj.hasOwnProperty(key)) {
//         newObj[key] = deepClone(obj[key]);
//       }
//     }

//     return newObj;
//   }

//   return obj;
// }

// 测试数据
var a = {
  name: "a",
  age: 2,
  info: {
    height: 17,
    weight: 100,
  },
  arry: [1, 2, 3],
  test: { inner: { innerinner: [1, 2, 3] } },
  ud: undefined,
  fn: function () {
    console.log(1);
  },
  date: [new Date(1536627600000), new Date(1540047600000)],
  nan: NaN,
  reg: new RegExp("\\w+"),
};
var b = deepClone(a);
b.age = 28;
b.name = "b";
b.arry[1] = "lc";
b.test.inner.innerinner[1] = "ok";
b.info.height = 168;
console.log(a, b);

c = [1, 2, 3, { inner: { innerinner: [1, 2, 3] } }];
d = deepClone(c);
d[0] = 0;
d[3].inner.innerinner[1] = 11;
console.log(c, d);
